//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <ddk.h>



#define DM9000_ID        0x90000A46

#define DR_GP_CONTROL       0x1e       // general purpose control
#define DR_GP_REGISTER      0x1f       // general purpose register

#define DM9000_REG00        0x00
#define DM9000_REG05        0x30        /* SKIP_CRC/SKIP_LONG */
#define DM9000_REG08        0x27
#define DM9000_REG09        0x38
#define DM9000_REG0A        0xff
#define DM9000_REGFF        0x83        /* IMR */

#define DM9000_PHY        0x40        /* PHY address 0x01 */
#define DM9000_PKT_MAX        1536        /* Received packet max size */
#define DM9000_PKT_RDY        0x01        /* Packet ready to receive */
#define DM9000_MIN_IO        0x300
#define DM9000_MAX_IO        0x370
#define DM9000_INT_MII        0x00
#define DM9000_EXT_MII        0x80


#define DR_PHY_ADDRBASE    0x10    // 10-15 : physical address registers
#define DR_MULTICASTBASE  0x16


#define DM9000_VID_L        0x28
#define DM9000_VID_H        0x29
#define DM9000_PID_L        0x2A
#define DM9000_PID_H        0x2B

#define DM9801_NOISE_FLOOR        0x08
#define DM9802_NOISE_FLOOR        0x05

#define DM9000SUCC               0
#define MAX_PACKET_SIZE         1514
#define DM9000MAX_MULTICAST         14

#define DM9000_RX_INTR        0x01
#define DM9000_TX_INTR        0x02
#define DM9000_OVERFLOW_INTR        0x04

#define DM9000_DWORD_MODE        1
#define DM9000_BYTE_MODE        2
#define DM9000_WORD_MODE        0

//#define DM9000TIMER_WUT       /* timer wakeup time : 2 second */
#define DM9000TX_TIMEOUT (10000000 *2)        /* tx packet time-out time 1.5 s" */

#define STDTIME    10

enum DM9000_PHY_mode {
    DM9000_10MHD   = 0,
        DM9000_100MHD  = 1,
        DM9000_10MFD   = 4,
        DM9000_100MFD  = 5,
        DM9000_AUTO    = 8,
        DM9000_1M_HPNA = 0x10
};

enum DM9000_NIC_TYPE {
    FASTETHER_NIC = 0,
        HOMERUN_NIC   = 1,
        LONGRUN_NIC   = 2
};

//#pragma pack(push,4)
struct DM9000_stats {
    int         rx_fifo_errors;
    int         rx_crc_errors;
    int  rx_length_errors;
    int  tx_packets;
    int  rx_packets;
};
/* Structure/enum declaration ------------------------------- */
typedef struct board_info {

    UInt32 runt_length_counter;        /* counter: RX length < 64byte */
    UInt32 long_length_counter;        /* counter: RX length > 1514byte */
    UInt32 reset_counter;/* counter: RESET */
    UInt32 reset_tx_timeout;/* RESET caused by TX Timeout */
    UInt32 reset_rx_status;/* RESET caused by RX Statsus wrong */

    UInt32 ioaddr;        /* Register I/O base address */
    UInt32 io_data;        /* Data I/O address */
    UInt16 irq;        /* IRQ */

    UInt16 tx_pkt_cnt;
    UInt16 queue_pkt_len;
    UInt16 queue_start_addr;
    UInt16 dbug_cnt;
    UInt8 reg0, reg5, reg8, reg9, rega;/* registers saved */
    UInt8 op_mode;        /* PHY operation mode */
    UInt8 io_mode;        /* 0:word, 2:byte */
    UInt8 phy_addr;
    UInt8 link_failed;        /* Ever link failed */
    UInt8 device_wait_reset;/* device state */
    UInt8 nic_type;        /* NIC type */
    //        struct timer_list timer;
    struct DM9000_stats stats;
    unsigned char srom[128];
 } board_info_t;



typedef struct DM9000 {
    DzCondition *     pRcondition;
    DzMutex *     pRmutex;
    DzCondition *     pWcondition;
    DzMutex *     pWmutex;
    DzEvent *         pISRevent; /* ist synch with isr */

    UInt32          base_addr;    /* bus space handle */
    int             irq;
    UInt8           reg_save;

    board_info_t   *board;
    unsigned char   dev_addr[6];
    UInt64          trans_start;
}DM9000,  *PDM9000;



void PDM9000_Init(PDM9000 pDm9000Dev);
UInt8 ior(board_info_t *, int);
void iow(board_info_t *, int, UInt8);
UInt16 phy_read(board_info_t *, int);
void phy_write(board_info_t *, int, UInt16);
UInt16 read_srom_word(board_info_t *, int);
void identify_nic(board_info_t *db);
void DM9000Receive(PDM9000  pDm9000Dev );
void DM900_MultCast(PDM9000  pDm9000Dev);
void DM900_SetMac(PDM9000  pDm9000Dev);
void set_PHY_mode(board_info_t *db);
int DM9000stop(PDM9000  pDm9000Dev);
Int32 DM9000Xmit(PDM9000    pDm9000Dev);



typedef unsigned long IO_PORT;
inline UInt32 IOSpaceReadInt32( IO_PORT port)
{
    return Inl(port);
}

inline void IOSpaceWriteInt32( IO_PORT port, UInt32 Value)
{
    Outl(port, Value);
}

inline UInt16 IOSpaceReadInt16( IO_PORT port)
{
    return Inw(port);
}

inline void IOSpaceWriteInt16( IO_PORT port, UInt16 Value)
{
    Outw(port, Value);
}


inline UInt8 IOSpaceReadInt8( IO_PORT port)
{
    return Inb(port);
}

inline void IOSpaceWriteInt8( IO_PORT port, UInt8 Value)
{
    Outb(port, Value);
}

